'use strict';

exports.__esModule = true;

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

/**
 * _
 * 
 * @param {Object} obj 
 * 
 * @example const a = { foo: 'bar', obj: { a: 1, b: 2 } };
 *          const b = deepClone(a); // a !== b, a.obj !== b.obj
 */
var deepClone = exports.deepClone = function deepClone(obj) {
  var clone = Object.assign({}, obj);
  Object.keys(clone).forEach(function (key) {
    return clone[key] = _typeof(obj[key]) === 'object' ? deepClone(obj[key]) : obj[key];
  });
  return clone;
};

/**
 * _
 * 
 * @param {Object} obj 
 * @param {Object[]} defs 
 * 
 * @example defaults({ a: 1 }, { b: 2 }, { b: 6 }, { a: 3 }); // { a: 1, b: 2 }
 */
var defaults = exports.defaults = function defaults(obj) {
  for (var _len2 = arguments.length, defs = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
    defs[_key2 - 1] = arguments[_key2];
  }

  return Object.assign.apply(Object, [{}, obj].concat(defs.reverse(), [obj]));
};

/**
 * _
 * 
 * @param {Object} a 
 * @param {Object} b
 * 
 * @example equals({ a: [2, { e: 3 }], b: [4], c: 'foo' }, { a: [2, { e: 3 }], b: [4], c: 'foo' }); // true 
 */
var equals = exports.equals = function equals(a, b) {
  if (a === b) return true;
  if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
  if (!a || !b || (typeof a === 'undefined' ? 'undefined' : _typeof(a)) != 'object' && (typeof b === 'undefined' ? 'undefined' : _typeof(b)) !== 'object') return a === b;
  if (a === null || a === undefined || b === null || b === undefined) return false;
  if (a.prototype !== b.prototype) return false;
  var keys = Object.keys(a);
  if (keys.length !== Object.keys(b).length) return false;
  return keys.every(function (k) {
    return equals(a[k], b[k]);
  });
};

/**
 * _
 * 
 * @param {Object} obj 
 * @param {Function} fn 
 * 
 * @example findKey(
 *            {
 *              barney: { age: 36, active: true },
 *              fred: { age: 40, active: false },
 *              pebbles: { age: 1, active: true }
 *            },
 *            o => o['active']
 *          ); // 'barney'
 */
var findKey = exports.findKey = function findKey(obj, fn) {
  return Object.keys(obj).find(function (key) {
    return fn(obj[key], key, obj);
  });
};

/**
 * _
 * 
 * @param {Object} obj 
 * @param {Function} fn 
 * 
 * findLastKey(
 * {
 *   barney: { age: 36, active: true },
 *   fred: { age: 40, active: false },
 *   pebbles: { age: 1, active: true }
 * },
 * o => o['active']
 * ); // 'pebbles'
 */
var findLastKey = function findLastKey(obj, fn) {
  return Object.keys(obj).reverse().find(function (key) {
    return fn(obj[key], key, obj);
  });
};

/**
 * flattenObject
 * 
 * @param {Object} obj
 * @param {String} [prefix = ''] 
 * 
 * @example
 * flattenObject({ a: { b: { c: 1 } }, d: 1 }); // { 'a.b.c': 1, d: 1 } 
 */
var flattenObject = exports.flattenObject = function flattenObject(obj) {
  var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';

  return Object.keys(obj).reduce(function (acc, k) {
    var pre = prefix.length ? prefix + '.' : '';
    if (_typeof(obj[k]) === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));else acc[pre + k] = obj[k];
    return acc;
  }, {});
};

/**
 * object get
 * 
 * @param {*} from 
 * @param {*} selectors 
 * 
 * @example
 * const obj = { selector: { to: { val: 'val to select' } }, target: [1, 2, { a: 'test' }] };
 * get(obj, 'selector.to.val', 'target[0]', 'target[2].a'); // ['val to select', 1, 'test']
 */
var get = exports.get = function get(from) {
  for (var _len3 = arguments.length, selectors = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
    selectors[_key3 - 1] = arguments[_key3];
  }

  return [].concat(selectors).map(function (s) {
    return s.replace(/\[([^\[\]]*)\]/g, '.$1.').split('.').filter(function (t) {
      return t !== '';
    }).reduce(function (prev, cur) {
      return prev && prev[cur];
    }, from);
  });
};

/**
 * _
 * 
 * @param {Object} obj 
 * @param {Function} fn 
 * 
 * @example mapKeys({ a: 1, b: 2 }, (val, key) => key + val); // { a1: 1, b2: 2 }
 */
var mapKeys = exports.mapKeys = function mapKeys(obj, fn) {
  return Object.keys(obj).reduce(function (acc, k) {
    acc[fn(obj[k], k, obj)] = obj[k];
    return acc;
  }, {});
};

/**
 * _
 * 
 * @param {Object} obj 
 * @param {Object} source 
 * @param {Function} fn 
 * 
 * @example
 * 
 * const isGreeting = val => /^h(?:i|ello)$/.test(val);
 * matchesWith(
 *    { greeting: 'hello' },
 *    { greeting: 'hi' },
 *    (oV, sV) => isGreeting(oV) && isGreeting(sV)
 * ); // true
 */
var matchesWith = exports.matchesWith = function matchesWith(obj, source, fn) {
  return Object.keys(source).every(function (key) {
    return obj.hasOwnProperty(key) && fn ? fn(obj[key], source[key], key, obj, source) : obj[key] == source[key];
  });
};

/**
 * _
 * 
 * @param {Paris[]} arr 
 * 
 * @example 
 * objectFromPairs([['a', 1], ['b', 2]]); // {a: 1, b: 2}
 */
var objectFromPairs = exports.objectFromPairs = function objectFromPairs(arr) {
  return arr.reduce(function (a, v) {
    return a[v[0]] = v[1], a;
  }, {});
};

/**
 * _
 * 
 * @param {Object} obj 
 * @param {Array} arr 
 * 
 * @example omitByKeys({ a: 1, b: '2', c: 3 }, ['b']); // { 'a': 1, 'c': 3 }
 */
var omitByKeys = exports.omitByKeys = function omitByKeys(obj, arr) {
  return Object.keys(obj).filter(function (k) {
    return !arr.includes(k);
  }).reduce(function (acc, key) {
    return acc[key] = obj[key], acc;
  }, {});
};

/**
 * _
 * 
 * @param {Object} obj 
 * @param {Function} fn 
 * 
 * @example omitBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number'); // { b: '2' }
 */
var omitBy = exports.omitBy = function omitBy(obj, fn) {
  return Object.keys(obj).filter(function (k) {
    return !fn(obj[k], k);
  }).reduce(function (acc, key) {
    return acc[key] = obj[key], acc;
  }, {});
};

/**
 * _
 * 
 * @param {Array} arr 
 * @param {Array} props
 * @param {Array} orders ['asc', 'desc']
 */
var orderBy = exports.orderBy = function orderBy(arr, props, orders) {
  return [].concat(arr).sort(function (a, b) {
    return props.reduce(function (acc, prop, i) {
      if (acc === 0) {
        var _ref = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]],
            p1 = _ref[0],
            p2 = _ref[1];

        acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
      }
      return acc;
    }, 0);
  });
};

/**
 * _
 * 
 * @param {Object} obj
 * @param {Array} arr  
 * 
 * @example pickByKeys({ a: 1, b: '2', c: 3 }, ['a', 'c']); // { 'a': 1, 'c': 3 }
 */
var pickByKeys = exports.pickByKeys = function pickByKeys(obj, arr) {
  return arr.reduce(function (acc, curr) {
    return curr in obj && (acc[curr] = obj[curr]), acc;
  }, {});
};

/**
 * unflattenObject
 * 
 * @param {*} obj 
 * 
 * @example unflattenObject({ 'a.b.c': 1, d: 1 }); // { a: { b: { c: 1 } }, d: 1 }
 */
var unflattenObject = exports.unflattenObject = function unflattenObject(obj) {
  return Object.keys(obj).reduce(function (acc, k) {
    if (k.indexOf('.') !== -1) {
      var keys = k.split('.');
      Object.assign(acc, JSON.parse('{' + keys.map(function (v, i) {
        return i !== keys.length - 1 ? '"' + v + '":{' : '"' + v + '":';
      }).join('') + obj[k] + '}'.repeat(keys.length)));
    } else acc[k] = obj[k];
    return acc;
  }, {});
};

/**
 * pickBy
 * 
 * @param {Object} obj 
 * @param {Function} fn 
 */
var pickBy = exports.pickBy = function pickBy(obj, fn) {
  return Object.keys(obj).filter(function (k) {
    return fn(obj[k], k);
  }).reduce(function (acc, key) {
    return acc[key] = obj[key], acc;
  }, {});
};

/**
 * 深度得到一个object
 * 
 * @param {Object} from 
 * @param {String} path 
 */
var deepGet = exports.deepGet = function deepGet(from) {
  for (var _len = arguments.length, selectors = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    selectors[_key - 1] = arguments[_key];
  }

  return [].concat(selectors).map(function (s) {
    return s.replace(/\[([^\[\]]*)\]/g, '.$1.').split('.').filter(function (t) {
      return t !== '';
    }).reduce(function (prev, cur) {
      return prev && prev[cur];
    }, from);
  });
};

/**
 * 深度得到一个object
 * 
 * @param {Object} obj 
 * @param {String} path 
 * @returns {Object | null} 
 */
var getByPath = exports.getByPath = function getByPath(obj, path) {
  var ret = deepGet(obj, path);
  if (ret) {
    return ret[0];
  }
  return null;
};